using System.Collections.Generic;
using System.Threading;
using IronPython.Hosting;
using IronPython.Runtime;
using Microsoft.Scripting.Hosting;
using System;

namespace visualtwimilar.Algorithms
{
  public static class PyClusters
  {
    private static readonly ScriptEngine Engine;
    //private static readonly Thread InitThread;
    private static readonly ScriptScope Scope;
    private static readonly ScriptSource Source;
    private static readonly IDictionary<string, object> Funcs = new Dictionary<string, object>();

    static PyClusters()
    {
      Engine = Python.CreateEngine();
      Scope = Engine.CreateScope();
      Source = Engine.CreateScriptSourceFromFile("Algorithms/clusters.py");
      //InitThread = new Thread(() =>
      //                          {
      Source.Compile().Execute(Scope);
      //});
      //InitThread.Start();
    }

    public static IDictionary<string, IList<T>> ScaleDown<T>(
      IDictionary<string, IDictionary<string, double>> prefs,
      double width, double height)
    {
      if (!Funcs.ContainsKey("scaledown"))
        Funcs.Add("scaledown", null);

      if (Funcs["scaledown"] == null)
      {
        var f = Scope.GetVariable<PythonFunction>("scaledown");
        Funcs["scaledown"] = Engine.Operations.ConvertTo<Func<
          IDictionary<string, IDictionary<string, double>>, double, double,
            IDictionary<string, IList<T>>>>(f);
      }
      var resultfunc = ((Func<
                           IDictionary<string, IDictionary<string, double>>, double, double,
          IDictionary<string, IList<T>>>)Funcs["scaledown"]);
      return resultfunc(prefs, width, height);
    }

    public static double SimPearson(IDictionary<string, IDictionary<string, double>> prefs, string person1, string person2)
    {
      if (!Funcs.ContainsKey("sim_pearson"))
        Funcs.Add("sim_pearson", null);

      if (Funcs["sim_pearson"] == null)
      {
        //InitThread.Join();
        var f = Scope.GetVariable<PythonFunction>("sim_pearson");
        Funcs["sim_pearson"] = Engine.Operations.ConvertTo<Func<IDictionary<string, IDictionary<string, double>>, string, string, double>>(f);
      }
      return ((Func<IDictionary<string, IDictionary<string, double>>, string, string, double>)Funcs["sim_pearson"])
        (prefs, person1, person2);
    }
  }
}